export class EventBus {
  private listeners: { [event: string]: Array<(...args: any[]) => void> } = {};

  /**
   * 注册一个事件监听器
   * @param event 事件名称
   * @param listener 监听函数
   */
  on(event: string, listener: (...args: any[]) => void): void {
    if (!this.listeners[event]) {
      this.listeners[event] = [];
    }
    this.listeners[event].push(listener);
  }

  /**
   * 注册一个只执行一次的事件监听器
   * @param event 事件名称
   * @param listener 监听函数
   */
  once(event: string, listener: (...args: any[]) => void): void {
    // 创建一个包装函数，调用原始监听器后自动移除
    const wrappedListener = (...args: any[]) => {
      // 先移除监听器，再调用，避免在回调中触发同一事件时出现死循环
      this.off(event, wrappedListener);
      listener(...args);
    };

    // 注册这个包装过的监听器
    this.on(event, wrappedListener);
  }

  /**
   * 移除事件监听器
   * @param event 事件名称
   * @param listener 需要移除的监听函数，如果不提供则移除该事件的所有监听器
   */
  off(event: string, listener?: (...args: any[]) => void): void {
    if (!this.listeners[event]) return;

    // 如果没有提供具体的监听器，则清空该事件的所有监听器
    if (!listener) {
      delete this.listeners[event];
      return;
    }

    // 否则只移除指定的监听器
    this.listeners[event] = this.listeners[event].filter((l) => l !== listener);
  }

  /**
   * 触发事件
   * @param event 事件名称
   * @param args 传递给监听器的参数
   */
  emit(event: string, ...args: any[]): void {
    if (!this.listeners[event]) return;
    this.listeners[event].forEach((listener) => listener(...args));
  }
}
